package com.example.factory.api.dto.assembler;

import com.example.factory.api.dto.DtoAuditDetails;
import com.example.factory.api.dto.DtoReport;
import com.example.factory.api.dto.DtoReporterReport;
import com.example.factory.api.dto.form.DtoReportForm;
import com.example.factory.core.domain.*;
import com.example.factory.core.repository.EquipmentRepository;
import com.example.factory.core.repository.ReportPlanRepository;
import com.example.factory.core.repository.UserRepository;
import com.example.factory.core.utils.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Lei Tao
 */
@Component
public class ReportAssembler {

    private final ReportPlanRepository reportPlanRepository;
    private final EquipmentRepository equipmentRepository;
    private final UserRepository userRepository;

    public ReportAssembler(ReportPlanRepository reportPlanRepository, EquipmentRepository equipmentRepository, UserRepository userRepository) {
        this.reportPlanRepository = reportPlanRepository;
        this.equipmentRepository = equipmentRepository;
        this.userRepository = userRepository;
    }

    @Transactional
    public ReportPlan toReport(DtoReportForm dtoReportForm) {
        ReportPlan reportPlan;
        if (!StringUtils.isEmpty(dtoReportForm.getGuid())) {
            reportPlan = reportPlanRepository.findByGuidAndArchivedFalse(dtoReportForm.getGuid());
        } else {
            reportPlan = new ReportPlan();
            reportPlan.setReportStatus(ReportStatus.CREATE);
        }
        BeanUtils.copyProperties(dtoReportForm, reportPlan);
        List<DtoReportForm.DtoEquipment> dtoEquipments = dtoReportForm.getDtoEquipments();
        List<ReportEquipment> reportEquipments = new ArrayList<>();
        for (DtoReportForm.DtoEquipment dtoEquipment : dtoEquipments) {
            ReportEquipment reportEquipment = new ReportEquipment();
            Equipment equipment = equipmentRepository.findByGuidAndArchivedFalse(dtoEquipment.getEquipmentGuid());
            reportEquipment.setEquipment(equipment);
            reportEquipment.setReportEquipmentStatus(ReportEquipmentStatus.CREATE);
            reportEquipments.add(reportEquipment);
        }
        reportPlan.cascadeUpdateReportEquipments(reportEquipments);
        return reportPlan;
    }

    public List<DtoReport> toDtoReports(List<ReportPlan> reportPlans) {
        List<DtoReport> dtoReports = new ArrayList<>();
        for (ReportPlan reportPlan : reportPlans) {
            DtoReport dtoReport = toDtoReport(reportPlan);
            dtoReports.add(dtoReport);
        }
        return dtoReports;
    }

    public DtoReport toDtoReport(ReportPlan reportPlan) {
        DtoReport dtoReport = new DtoReport();
        List<DtoReport.DtoEquipment> dtoEquipments = toDtoEquipments(reportPlan);
        dtoReport.setDtoEquipments(dtoEquipments);
        dtoReport.setGuid(reportPlan.getGuid());
        dtoReport.setReportStatus(reportPlan.getReportStatus().name());
        if (!StringUtils.isEmpty(reportPlan.getGradingPeopleGuid())) {
            dtoReport.setGradingPeopleGuid(reportPlan.getGradingPeopleGuid());
            UserEntity gradingPeople = userRepository.findByGuidAndArchivedFalse(reportPlan.getGradingPeopleGuid());
            dtoReport.setGradingPeopleName(gradingPeople.getName());
        }
        if (!StringUtils.isEmpty(reportPlan.getReporterGuid())) {
            dtoReport.setReporterGuid(reportPlan.getReporterGuid());
            UserEntity reporter = userRepository.findByGuidAndArchivedFalse(reportPlan.getReporterGuid());
            dtoReport.setReporterName(reporter.getName());
        }
        return dtoReport;
    }

    public List<DtoReport.DtoEquipment> toDtoEquipments(ReportPlan reportPlan) {
        List<DtoReport.DtoEquipment> dtoEquipments = new ArrayList<>();
        List<ReportEquipment> reportEquipments = reportPlan.getReportEquipments();
        for (ReportEquipment reportEquipment : reportEquipments) {
            DtoReport.DtoEquipment dtoEquipment = new DtoReport.DtoEquipment();
            if (reportEquipment != null) {
                dtoEquipment.setGuid(reportEquipment.getGuid());
                Equipment equipment = reportEquipment.getEquipment();
                if (equipment != null) {
                    dtoEquipment.setName(equipment.getName());
                    dtoEquipment.setEquipmentGuid(equipment.getGuid());
                    dtoEquipment.setReportEquipmentStatus(reportEquipment.getReportEquipmentStatus().name());
                }
            }
            dtoEquipments.add(dtoEquipment);
        }
        return dtoEquipments;
    }

    public DtoReporterReport toDtoReporterReport(ReportPlan reportPlan) {
        DtoReporterReport dtoReporterReport = new DtoReporterReport();
        String createTime = reportPlan.getCreatedDateTime().format(DateUtils.DEFAULT_DATE_TIME_FORMAT);
        dtoReporterReport.setCreateTime(createTime);
        UserEntity reporter = userRepository.findByGuidAndArchivedFalse(reportPlan.getReporterGuid());
        dtoReporterReport.setReporterName(reporter.getName());
        dtoReporterReport.setReportPlanGuid(reportPlan.getGuid());
        String content = reportPlan.getContent();
        dtoReporterReport.setContent(content);
        return dtoReporterReport;
    }

    public List<DtoAuditDetails> toDtoAuditDetails(ReportPlan reportPlan) {
        List<DtoAuditDetails> dtoAuditDetails = new ArrayList<>();
        List<ReportEquipment> reportEquipments = reportPlan.getReportEquipments();
        for (ReportEquipment reportEquipment : reportEquipments) {
            DtoAuditDetails dtoAuditDetail = new DtoAuditDetails();
            Equipment equipment = reportEquipment.getEquipment();
            dtoAuditDetail.setEquipmentName(equipment.getName());
            dtoAuditDetail.setGuid(reportEquipment.getGuid());
            ReportLevel1Dimension reportLevel1Dimension = reportEquipment.getReportLevel1Dimension();
            if (reportLevel1Dimension != null) {
                dtoAuditDetail.setLevel1Name(reportLevel1Dimension.getLevel1Dimension().getName());
                UserEntity scorer = userRepository.findByGuidAndArchivedFalse(reportPlan.getGradingPeopleGuid());
                dtoAuditDetail.setScorerName(scorer.getName());
                dtoAuditDetail.setWeight(reportLevel1Dimension.getLevel1Dimension().getWeight().toString());
                List<ReportLevel2Dimension> reportLevel2Dimensions = reportLevel1Dimension.getReportLevel2Dimensions();
                List<DtoAuditDetails.level2> level2s = new ArrayList<>();
                for (ReportLevel2Dimension reportLevel2Dimension : reportLevel2Dimensions) {
                    DtoAuditDetails.level2 level2 = new DtoAuditDetails.level2();
                    Level2Dimension level2Dimension = reportLevel2Dimension.getLevel2Dimension();
                    level2.setScore(reportLevel2Dimension.getScore().toString());
                    level2.setDescription(level2Dimension.getDescription());
                    level2.setLevel2Name(level2Dimension.getName());
                    level2.setMax(level2Dimension.getMax());
                    level2.setMin(level2Dimension.getMin());
                    level2s.add(level2);
                }
                dtoAuditDetail.setLevel2s(level2s);
            }
            dtoAuditDetails.add(dtoAuditDetail);
        }
        return dtoAuditDetails;
    }
}
